/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#ifndef INCLUDE_SHADER_BUILT_IN_FUNCTIONS
#define INCLUDE_SHADER_BUILT_IN_FUNCTIONS


#include "shader_std.h"



#define DEF_ForwardDir 1

#define DEF_Blend_Normal      0       //正常
#define DEF_Blend_Screen      1       //滤色    ：与正片叠底相反，将上层图层的颜色与下层图层相加，通常会使图像变亮。
#define DEF_Blend_Multiply    2       //正片叠底：将上层图层的颜色与下层图层相乘，通常会使图像变暗。

#define DEF_Blend_Dissolve    3       //溶解    ：在两个图层之间创建颗粒状的过渡效果，类似于颗粒状的溶解过程。
#define DEF_Blend_Darken      4       //变暗    ：选择两个图层中较暗的颜色。
#define DEF_Blend_ColorBurn   5       //颜色加深：类似于正片叠底，但会保留下层图层的高光部分。
#define DEF_Blend_LinearBurn  6       //线性加深：类似于颜色加深，但对比度更强。
#define DEF_Blend_Lighten     7       //变亮    ：选择两个图层中较亮的颜色。

#define DEF_Blend_ColorDodge  8       //颜色减淡：类似于滤色，但会保留下层图层的阴影部分。
#define DEF_Blend_LinearDodge 9       //线性减淡：类似于颜色减淡，但对比度更强。
#define DEF_Blend_Overlay     10      //叠加    ：根据上层图层的颜色值，选择变暗或变亮。
#define DEF_Blend_SoftLight   11      //柔光    ：类似于使用柔光灯照射，增强对比度和饱和度。
#define DEF_Blend_HardLight   12      //强光    ：类似于柔光，但效果更强烈。
#define DEF_Blend_Difference  13      //差值    ：计算两个图层颜色值的差，产生对比强烈的效果。
#define DEF_Blend_Exclusion   14      //排除    ：类似于差值，但对比度较低。
#define DEF_Blend_Hue         15      //色相    ：保留下层图层的亮度和饱和度，使用上层图层的色相。
#define DEF_Blend_Saturation  16      //饱和度  ：保留下层图层的亮度和色相，使用上层图层的饱和度。
#define DEF_Blend_Color       17      //颜色    ：保留下层图层的亮度，使用上层图层的色相和饱和度。
#define DEF_Blend_Luminosity  18      //明度    ：保留上层图层的亮度，使用下层图层的色相和饱和度。


#define DEF_Texture_Type_1D        0
#define DEF_Texture_Type_1DArray   1
#define DEF_Texture_Type_2D        2
#define DEF_Texture_Type_2DArray   3
#define DEF_Texture_Type_3D        4
#define DEF_Texture_Type_3DArray   5
#define DEF_Texture_Type_Cube      6
#define DEF_Texture_Type_CubeArray 7

#ifdef __cplusplus

// GLSL Type
using uint = unsigned int;
using uint64_t = uint64;

#define in
#define out
#define inout


#include <向量.h>


#else

#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference2 : require

#define Inline

#endif



struct S_CustomAttr {
	uint64_t offset;
	uint64_t num;
};



struct S_PBF_Params {
	
	vec3 m_Gravity;
	vec3 m_Wind;

	
	float		m_cellSize;
	float		m_dt;

	//int numIterations;
	int numSubsteps;


	float radius;
	float solidRestDistance;
	float fluidRestDistance;
	float rest_density;

	// cloth params
	float drag;
	float lift;

	float cohesion;
	float surfaceTension;
	float viscosity;
	float vorticityConfinement;
	float anisotropyScale;
	float anisotropyMin;
	float anisotropyMax;
	float smoothing;
	float solidPressure;
	float freeSurfaceDrag;
	float buoyancy;


	// diffuse params
	// 速度阈值
	float diffuseThreshold;
	//飞溅粒子浮力
	float diffuseBuoyancy;
	//飞溅粒子阻力
	float diffuseDrag;
	//浮力
	int   diffuseBallistic;
	//寿命
	float diffuseLifetime;



	// common params
	float dynamicFriction;
	float staticFriction;
	float particleFriction;
	float restitution;
	float adhesion;
	float sleepThreshold;
	float maxSpeed;
	float maxAcceleration;
	float shockPropagation;
	float dissipation;
	float damping;



	// collision params
	float collisionDistance;
	float particleCollisionMargin;
	float shapeCollisionMargin;



	float relaxationFactor;
	//uint32	m_飞溅粒子数量;
	//uint32	m_粒子数量;
};





//随机种子
Inline uint f_tea(uint val0, uint val1) {
	uint v0 = val0;
	uint v1 = val1;
	uint s0 = 0;

	for (uint n = 0; n < 16; ++n) {
		s0 += 0x9e3779b9;
		v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
		v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
	}
	return v0;
}
// 生成 [0, 2^24) 随机数
Inline uint f_lcg(in uint prev) {
	uint LCG_A = 1664525u;
	uint LCG_C = 1013904223u;
	prev = (LCG_A * prev + LCG_C);
	return prev & 0x00FFFFFF;
}


Inline float f_rnd(in uint prev) {
	return (float(f_lcg(prev)) / float(0x01000000));
}
Inline vec2 f_rnd(in vec2 prev) {
	vec2 r;
	r.x = (float(f_lcg(uint(prev.x))) / float(0x01000000));
	r.y = (float(f_lcg(uint(prev.y))) / float(0x01000000));
	return r;
}







#ifdef __cplusplus

#include <basic_vec.h>
#include <向量.h>
#include <math.h>
#include <公共函数.h>



Inline vec2 clamp(vec2 x, float32 minVal, float32 maxVal) {
	return {DEF_Min(DEF_Max(x.x, minVal), maxVal), DEF_Min(DEF_Max(x.y, minVal), maxVal)};
}
Inline vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal) {
	return { DEF_Min(DEF_Max(x.x, minVal.x), maxVal.x), DEF_Min(DEF_Max(x.y, minVal.y), maxVal.y), DEF_Min(DEF_Max(x.z, minVal.z), maxVal.z) };
}


Inline vec2 floor(vec2 v) {
	return { float32(int32(v.x)), float32(int32(v.y)) };
}

Inline vec3 floor(vec3 v) {
	return { float32(int32(v.x)), float32(int32(v.y)), float32(int32(v.z)) };
}

Inline int32 step(float32 edge, float32 x) {
	return (x < edge) ? 0 : 1;
}

Inline vec3 step(float32 edge, vec3& x) {
	return vec3{float32(step(edge, x.x)), float32(step(edge, x.y)), float32(step(edge, x.z))};
}

Inline vec3 step(const vec3& edge, const vec3& x) {
	return vec3{ float32(step(edge.x, x.x)), float32(step(edge.y, x.y)), float32(step(edge.z, x.z)) };
}



Inline vec2 abs(const vec2& x) {
	return vec2{ abs(x.x), abs(x.y) };
}
Inline vec3 abs(const vec3& x) {
	return vec3{ abs(x.x), abs(x.y) ,abs(x.z) };
}
Inline vec4 abs(const vec4& x) {
	return vec4{ abs(x.x), abs(x.y), abs(x.z), abs(x.w) };
}

Inline float32 fract(float32 v) {
	return v - floor(v);
}

Inline vec2 fract(vec2 v) {
	return { v.x - floor(v.x), v.y - floor(v.y) };
}

Inline vec3 fract(vec3 v) {
	return { v.x - floor(v.x), v.y - floor(v.y), v.z - floor(v.z) };
}

Inline float32 mod(float32 x, float32 y) {
	return x - y * floor(x / y);
}
Inline vec2 mod(vec2& x, vec2& y) {
	return x - y * floor(x / y);
}



Inline vec2 round(vec2 v) {
	vec2 r;

	if (v.x < 0) {
		r.x = -floor(-v.x + 0.5);
	}
	else {
		r.x = floor(v.x + 0.5);
	}

	if (v.y < 0) {
		r.y = -floor(-v.y + 0.5);
	}
	else {
		r.y = floor(v.y + 0.5);
	}

	return r;
}

Inline vec3 round(vec3 v) {
	vec3 r;

	if (v.x < 0) {
		r.x = -floor(-v.x + 0.5);
	}
	else {
		r.x = floor(v.x + 0.5);
	}

	if (v.y < 0) {
		r.y = -floor(-v.y + 0.5);
	}
	else {
		r.y = floor(v.y + 0.5);
	}

	if (v.z < 0) {
		r.z = -floor(-v.z + 0.5);
	}
	else {
		r.z = floor(v.z + 0.5);
	}

	return r;
}



Inline float32 degrees(float32 弧度) {
	return M_弧度转角度(弧度);
}

Inline vec4 normalize(const vec4& vec) {
	float32 逆向长度 = f_逆平方根(dot(vec, vec));
	return vec * 逆向长度;
}

Inline float32 roundEven(const float32& v) {
	int32 a = ((int32)v);
	int32 b = round(fabs(v));
	int32 s = a >= 0 ? 1 : -1;

	if(a % 2 == 0) return s * b;
	else if(b > fabs(a)) return s * (b-1);
	else return s * b;
	return {};
}

Inline float f_random(const vec3& p) {
	return fract(sin(dot(p, vec3{12.9898, 78.233, 45.5432})) * 43758.5453);
}

Inline vec3 f_cartesianToSpherical(vec3 pos) {
	vec3 coord;

	//pos.xyz = pos.xzy;
	float32 temp = pos.z;
	pos.x = pos.x;
	pos.z = pos.y;
	pos.y = temp;

	coord.z = length(pos);
	pos *= 1.0f / coord.z;
	coord.y = acos(pos.z);

	coord.x = atan2(pos.y, pos.x);
	coord.x += coord.x < 0 ? 2*M_PI : 0;

	return coord;
}

/******************************************** 矢量计算 **********************************************/



inline float32 cross(const vec2& a, const vec2& b) {
	return  a.x * b.y - a.y * b.x;
}







/******************************************** 相交计算 **********************************************/

//线段相交
inline void f_ClosestPointBetweenLineSegments(const vec3& p, const vec3& q, const vec3& r, const vec3& s, float& u, float& v) {
	//vec3 d1 = q - p;
	vec3 d1 = q;
	//vec3 d2 = s - r;
	vec3 d2 = s;
	vec3 rp = p - r;
	float a = dot(d1, d1);
	float c = dot(d1, rp);
	float e = dot(d2, d2);
	float f = dot(d2, rp);

	float b = dot(d1, d2);
	float denom = a * e - b * b;
	if (denom != 0.0f)
		u = clamp((b * f - c * e) / denom, 0.0f, 1.0f);
	else {
		u = 0.0f;
	}

	v = (b * u + f) / e;

	if (v < 0.0f) {
		v = 0.0f;
		u = clamp(-c / a, 0.0f, 1.0f);
	}
	else if (v > 1.0f) {
		v = 1.0f;
		u = clamp((b - c) / a, 0.0f, 1.0f);
	}
}











//Inline float f_graph_point_to_plane_dis(in vec4 plane, in vec3 point) {
//	vec3 t = {plane.x, plane.y, plane.z};
//	t = point * t;
//	t = t - plane.w;
//	return dot(t, t);
//}

Inline float f_graph_point_to_plane_dis(in vec4 plane, in vec3 point) {
	return plane.x * point.x + plane.y * point.y + plane.z * point.z + plane.w;
}


#define DEF_graph_vec_build_quat Inline vec4 f_graph_vec_build_quat(const vec3& dir, float angle)
#define DEF_graph_quatTranformInv Inline vec3 f_graph_quatTranformInv(const vec4& q, const vec3& pos)
#define DEF_surface_FaceNormal Inline vec3 f_surface_FaceNormal(const vec3& v0, const vec3& v1, const vec3& v2)
#define DEF_glsl_CoordToIndex Inline uint f_glsl_CoordToIndex(const uvec3& coord, const uvec3& dim)
#define DEF_glsl_IndexToCoord Inline ivec3 f_glsl_IndexToCoord(const uint32 index, const uvec3& dim)
#define DEF_glsl_bspline Inline float32 f_glsl_bspline(const vec3& dis, float r)
#define DEF_glsl_quadratic Inline float32 f_glsl_quadratic(const vec3& dis, float r)
#define DEF_glsl_polynomial Inline float32 f_glsl_polynomial(float d, float r)
#define DEF_glsl_calculateTangentPoints Inline void f_glsl_calculateTangentPoints(const vec2 center[2], const float r[2], vec2 tp[2])
//#define DEF_glsl_vertToCoord Inline float32 f_glsl_vertToCoord(const vec3& v0, const vec3& v1)
//Inline vec2 f_rot_vec(const vec2& point, float angle) {
//	mat2 mat;
//	mat.m0 = {cos(angle), -sin(angle)};
//	mat.m1 = {sin(angle), cos(angle)};
//
//	return mat * point;
//}


//缩放到区域
Inline vec2 f_TileTextureSamplCoord(const vec2& sampl, const vec2& tileSize, const ivec2& tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	ivec2 IDCoord = _iVec2(sp);
	if (IDCoord == tileID) {
		sp = abs(sp - IDCoord);
	}
	else {
		sp = {};
	}
	return sp;
}
//缩放到区域保持比例
Inline vec2 f_TileTextureSamplkeepCoord(const vec2& sampl, const vec2& tileSize, const ivec2& tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	ivec2 IDCoord = _iVec2(sp);
	if (IDCoord == tileID) {
		sp = sampl;
	}
	else {
		sp = {};
	}
	return sp;
}
//使用切分的区域
Inline vec2 f_TileTextureSamplLocCoord(const vec2& sampl, const vec2& tileSize, const ivec2& tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	sp = sampl * tileSize;
	return sp;
}

Inline vec3 f_glsl_vertToCoord(const vec3& v0, float32 u) {
	return {roundEven(v0.x / u), roundEven(v0.y / u), roundEven(v0.z / u) };
}



Inline float32 UintBitFloat(uint32 val) {
	return *((float32*)&val);
}

Inline float32 glsl_RGBAToFloat(S_RGBA8UI color) {
	return UintBitFloat(f_PackData4X8(color));
}






Inline bool f_glsl_rayIntersectBox(vec3 rayOrigin, vec3 rayDirection, vec3 boxMin, vec3 boxMax) {
	// 将射线起点转换到包围盒局部坐标系
	//vec3 localOrigin = rayOrigin - boxCenter;

	// 计算射线与各平面的交点（处理方向向量为零的安全情况）
	vec3 invDirection = _Vec3(1.0) / (rayDirection + 1.0-8);

	vec3 tMin = (boxMin - rayOrigin) * rayDirection;
	vec3 tMax = (boxMax - rayOrigin) * rayDirection;

	// 确保tMin包含最小的t值，tMax包含最大的t值
	vec3 t1 = min(tMin, tMax);
	vec3 t2 = max(tMin, tMax);

	// 计算最终的tMin和tMax
	float32 tNear = max(max(t1.x, t1.y), t1.z);
	float32 tFar = min(min(t2.x, t2.y), t2.z);

	//return t1.x >= boxMin.x && t1.y >= boxMin.y && t1.z >= boxMin.z && t2.x >= boxMax.x && t2.y >= boxMax.y && t2.z >= boxMax.z;
	return tFar >= tNear && tFar >= 0;
}

Inline bool f_glsl_isIntersecting(vec3 rayOrigin, vec3 rayDirection, vec3 boxMin, vec3 boxMax) {
	float32 la = (boxMin.x - rayOrigin.x) * rayDirection.x;
	float32 lb = (boxMax.x - rayOrigin.x) * rayDirection.x;
	float32 tMin = min(la, lb);
	float32 tMax = max(la, lb);

	la = (boxMin.y - rayOrigin.y) * rayDirection.y;
	lb = (boxMax.y - rayOrigin.y) * rayDirection.y;
	tMin = max(min(la, lb), tMin);
	tMax = min(max(la, lb), tMax);

	la = (boxMin.z - rayOrigin.z) * rayDirection.z;
	lb = (boxMax.z - rayOrigin.z) * rayDirection.z;
	tMin = max(min(la, lb), tMin);
	tMax = min(max(la, lb), tMax);

	return tMax >= tMin & tMax >= 0;

	//vec2 tValues = f_glsl_rayIntersectBox(rayOrigin, rayDirection, boxCenter, boxSize);
	//return tValues.x <= tValues.y && tValues.y >= 0.0;
}


Inline mat4 f_glsl_removeRotation(mat4 matix) {
	vec4 translation = matix.m3;

	float32 scaleX = length(_Vec3(matix.m0));
	float32 scaleY = length(_Vec3(matix.m1));
	float32 scaleZ = length(_Vec3(matix.m2));

	matix.m0 = {scaleX, 0, 0, 0};
	matix.m1 = {0, scaleY, 0, 0};
	matix.m2 = {0, 0, scaleZ, 0};
	matix.m3 = translation;

	return matix;
}

Inline mat4 f_glsl_removePostion(mat4 matix) {
	matix.m3.x = 0;
	matix.m3.y = 0;
	matix.m3.z = 0;
	return matix;
}



#else

#define M_PI   3.1415926535
#define M_PI_H 1.570796326794


struct S_VNT1 {
	vec3 vert;
	vec3 normal;
	vec2 UV;
};




#extension GL_EXT_scalar_block_layout : enable
#extension GL_EXT_buffer_reference2 : require


layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_I32 { int   i32Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_UI32 { uint ui32Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_UI64 { uint64_t ui64Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_F32 { float f32Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_Vec2 { vec2  vec2Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_Vec3 { vec3  vec3Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_Vec4 { vec4  vec4Ptr[]; };

layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_iVec2 { ivec2  ivec2Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_iVec3 { ivec3  ivec3Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_iVec4 { ivec4  ivec4Ptr[]; };

layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_UVec2 { uvec2  uvec2Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_UVec3 { uvec3  uvec3Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_UVec4 { uvec4  uvec4Ptr[]; };
layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_Mat4 { mat4  mat4Ptr[]; };

layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_PBF_SimParam { S_PBF_Params  simPtr[]; };




layout(buffer_reference, scalar) buffer W_GlobalParameter_I32 { int   i32Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_UI32 { uint   ui32Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_F32 { float f32Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_Vec2 { vec2  vec2Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_Vec3 { vec3  vec3Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_Vec4 { vec4  vec4Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_UVec2 { uvec2  uvec2Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_UVec3 { uvec3  uvec3Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_UVec4 { uvec4  uvec4Ptr[]; };
layout(buffer_reference, scalar) buffer W_GlobalParameter_Mat4 { mat4  mat4Ptr[]; };

layout(buffer_reference, scalar) readonly	buffer R_GlobalParameter_VNT1 { S_VNT1 vertPtr[]; };
layout(buffer_reference, scalar) buffer		W_GlobalParameter_VNT1 { S_VNT1 vertPtr[]; };

layout(buffer_reference, scalar) readonly buffer R_GlobalParameter_CustomAttr { S_CustomAttr  CustomAttrPtr[]; };
layout(buffer_reference, scalar) buffer          W_GlobalParameter_CustomAttr { S_CustomAttr  CustomAttrPtr[]; };
layout(buffer_reference, scalar) buffer          W_GlobalParameter_Force { S_PBF_force  forcePtr[]; };





float f_graph_point_to_plane_dis(in vec4 plane, in vec3 point) {
	vec3 t = vec3(plane.x, plane.y, plane.z );
	t = point * t;
	t = t - plane.w;
	return dot(t, t);
}


float atan2(in float y, in float x) {
	bool s = abs(x) > abs(y);
	return mix(M_PI/2 - atan(x,y), atan(y,x), s);
}


//�ѿ������굽��������
Inline vec3 f_cartesianToSpherical(vec3 pos) {
	vec3 coord;

	pos.xyz = pos.xzy;

	coord.z = length(pos);
	pos *= 1.0f / coord.z;
	coord.y = acos(pos.z);

	coord.x = atan2(pos.y, pos.x);
	coord.x += coord.x<0 ? 2*M_PI : 0;

	return coord;
}



#define DEF_graph_vec_build_quat vec4 f_graph_vec_build_quat(in vec3 dir, float angle)
#define DEF_graph_quatTranformInv Inline vec3 f_graph_quatTranformInv(in vec4 q, in vec3 pos)
#define DEF_surface_FaceNormal vec3 f_surface_FaceNormal(in vec3 v0, in vec3 v1, in vec3 v2)
#define DEF_glsl_CoordToIndex uint f_glsl_CoordToIndex(in uvec3 coord, in uvec3 dim)
#define DEF_glsl_IndexToCoord ivec3 f_glsl_IndexToCoord(in uint index, in uvec3 dim)
#define DEF_glsl_bspline Inline float f_glsl_bspline(in vec3 dis, float r)
#define DEF_glsl_quadratic Inline float f_glsl_quadratic(in vec3 dis, float r)
#define DEF_glsl_polynomial Inline float f_glsl_polynomial(float d, float r)
#define DEF_glsl_vertToCoord Inline float32 f_glsl_vertToCoord(in vec3 v0, in vec3 v1)
#define DEF_glsl_calculateTangentPoints void f_glsl_calculateTangentPoints(in vec2 center[2], in float r[2], out vec2 tp[2])


Inline vec2 f_TileTextureSamplCoord(in vec2 sampl, in vec2 tileSize, in ivec2 tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	ivec2 IDCoord = ivec2(sp);
	if (IDCoord == tileID) {
		sp = abs(sp - IDCoord);
	}
	else {
		sp = ivec2(1,0);
	}
	return sp;
}
//缩放到区域保持比例
Inline vec2 f_TileTextureSamplkeepCoord(in vec2 sampl, in vec2 tileSize, in ivec2 tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	ivec2 IDCoord = ivec2(sp);
	if (IDCoord == tileID) {
		sp = sampl;
	}
	else {
		sp = vec2(0);
	}
	return sp;
}
//使用切分的区域
Inline vec2 f_TileTextureSamplLocCoord(in vec2 sampl, in vec2 tileSize, in ivec2 tileID) {
	vec2 sp = sampl / tileSize;
	if (sp.x < 0) sp.x -= 1;
	if (sp.y < 0) sp.y -= 1;

	ivec2 IDCoord = ivec2(sp);

	sp = abs(sampl * tileSize);
	sp += tileID * tileSize;
	return sp;
}

vec3 f_glsl_vertToCoord(in vec3 v0, in float u) {
	return vec3( roundEven(v0 / u) );
}


//椭圆
Inline float f_ellipse(vec2 uv, in vec2 center, in vec2 v, vec2 radius) {
	float angle = atan(v.y, v.x);

	//mat2 m = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
	//vec2 norm = m * (uv - center);

	vec2 norm = (uv - center);
	float dist = length(norm / radius);
	return dist;
}


vec2 f_rotDir(in vec2 uv, in vec2 v) {
	float angle = atan(v.y, v.x);
	mat2 m = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
	return m * uv;
}





float glsl_hitSphere(const S_Sphere s, const S_Ray2 r) {
	vec3  oc = r.origin - s.pos;
	float a = dot(r.direction, r.direction);
	float b = 2.0 * dot(oc, r.direction);
	float c = dot(oc, oc) - s.radius * s.radius;
	float discriminant = b * b - 4 * a * c;
	if (discriminant < 0) {
		return -1.0;
	}
	else {
		return (-b - sqrt(discriminant)) / (2.0 * a);
	}
}

// Ray-AABB intersection
float glsl_hitAabb(const S_Aabb aabb, const S_Ray2 r) {
	vec3  invDir = 1.0 / r.direction;
	vec3  tbot = invDir * (aabb.minimum - r.origin);
	vec3  ttop = invDir * (aabb.maximum - r.origin);
	vec3  tmin = min(ttop, tbot);
	vec3  tmax = max(ttop, tbot);
	float t0 = max(tmin.x, max(tmin.y, tmin.z));
	float t1 = min(tmax.x, min(tmax.y, tmax.z));
	return t1 > max(t0, 0.0) ? t0 : -1.0;
}


// Randomly sampling around +Z
vec3 samplingHemisphere(inout uint seed, in vec3 x, in vec3 y, in vec3 z) {
	float r1 = f_rnd(seed);
	float r2 = f_rnd(seed);
	float sq = sqrt(1.0 - r2);

	vec3 direction = vec3(cos(2 * M_PI * r1) * sq, sin(2 * M_PI * r1) * sq, sqrt(r2));
	direction = direction.x * x + direction.y * y + direction.z * z;

	return direction;
}

// Return the tangent and binormal from the incoming normal
void createCoordinateSystem(in vec3 N, out vec3 Nt, out vec3 Nb) {
	if (abs(N.x) > abs(N.y))
		Nt = vec3(N.z, 0, -N.x) / sqrt(N.x * N.x + N.z * N.z);
	else
		Nt = vec3(0, -N.z, N.y) / sqrt(N.y * N.y + N.z * N.z);
	Nb = cross(N, Nt);
}



//float f_ind2sub(uvec2 uv, in uvec2 center, uint index) {
//	float angle = atan(v.y, v.x);
//
//	mat2 m = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
//
//	vec2 norm = m * (uv - center);
//	float dist = length(norm / radius);
//	return dist;
//}


//void vec3 f_glsl_ColorBlend(in vec3 colA, in vec3 colB) {
//
//}

float f_random(in vec3 p) {
	return fract(sin(dot(p, vec3(12.9898, 78.233, 45.5432))) * 43758.5453);
}

// 随机数生成函数
float f_random(in vec2 co) {
	return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
}


// 生成 vec3 类型的随机向量
vec3 f_random3(in vec3 co) {
	// 对vec3的每个分量使用不同的扰动来生成随机数
	float r1 = f_random(co.xy + vec2(0.0, 1.0));
	float r2 = f_random(co.yz + vec2(1.0, 0.0));
	float r3 = f_random(co.zx + vec2(1.0, 1.0));

	// 将随机数组合成vec3向量
	return vec3(r1, r2, r3);
}

Inline vec3 f_SphereSampling_toWorld_noise(vec3 ss, vec3 N) {
	vec3 up;
	up.x = 0.0;
	up.y = 1;
	up.z = 0.0;

	up += f_random3(ss + N) * 0.0001;

	vec3 right = normalize(cross(up, N));
	up = normalize(cross(N, right));

	return right * ss.x + N * ss.y + up * ss.z;
}





/************************************ UI *****************************************/


void glsl_FrameSampleLayerAttr(in S_FrameSample_TAA fs, out uint franeCount, out uint layerOffset, out uint areaNum) {
	franeCount = fs.m_LayerAttr & 0xff;
	layerOffset = (fs.m_LayerAttr >> 8) & 0xff;
	areaNum = (fs.m_LayerAttr >> 16) & 0xff;
	
}
void glsl_UnPack_FSLayerAttr(in S_FrameSample_TAA fs, out uvec2 offset, out uvec2 size) {
	offset.x = fs.m_LayerArea_Offset & 0xffff;
	offset.y = (fs.m_LayerArea_Offset>>16) & 0xffff;
	size.x = (fs.m_LayerArea_Size) &0xffff;
	size.y = (fs.m_LayerArea_Size >> 16) &0xffff;
}

void glsl_UnPack_LayerArea(in S_FrameSample_TAA fs, out uvec2 offset, out uvec2 size, out bool isUpdate, out uint debug) {
	offset.x = fs.m_LayerArea_Offset & 0xffff;
	offset.y = (fs.m_LayerArea_Offset>>16) & 0xffff;
	size.x = (fs.m_LayerArea_Size) &0xffff;
	size.y = (fs.m_LayerArea_Size >> 16) &0xffff;

	isUpdate = bool(fs.m_LayerAttr & 0xff);
	debug = uint(fs.m_LayerAttr >> 8) & 0xff;
}


void glsl_ConstPush_UnPack_LayerAttr(in S_ConstPush_TAA fs, out uint layerID, out uint layerNum) {
	layerID = fs.m_LayerAttr & 0xff;
	layerNum = (fs.m_LayerAttr >> 8) & 0xff;
}



float glsl_sdRoundBox( in vec2 p, in vec2 b, in vec4 r ) {
	r.xy = (p.x>0.0) ? r.xy : r.zw;
	r.x  = (p.y>0.0) ? r.x  : r.y;
	vec2 q = abs(p)-b+r.x;
	return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r.x;
}


#endif




struct S_2DICO_PanelAttr {
	uint m_Offset_Instance;
};

struct S_2DChar_PanelAttr {
	uint m_CharSize;
	uint m_Offet_Char;
	uint m_Offet_CharUV;
	uint m_AlignType;

	uint m_Offset_Instance;
};


/******************************************** 几何计算 ***********************************************/

Inline vec4 f_plane(in vec3 point, in vec3 normal){
	vec4 plane;
	plane.x = normal.x;
	plane.y = normal.y;
	plane.z = normal.z;
	plane.w = -dot(normalize(point), normal);
	return plane;
}



Inline float f_point_to_line_dis(in vec2 point, in vec2 p0, in vec2 p1){
	float a = length(p1 - p0);
	vec2 pv0 = point - p0;
	vec2 pv1 = point - p1;
	
	float hypotenuse_0 = length(pv0);
	float hypotenuse_1 = length(pv1);

	if(hypotenuse_0 < 1e-6 || hypotenuse_1 < 1e-6) return 0;

	float c = pow(hypotenuse_0 + hypotenuse_1, 2);
	a = pow(a, 2);
	float b = sqrt(c - a);
	return b;

}

Inline float f_vec_to_angle(in vec2 v1, in vec2 v2) {
	float A = dot(v1, v2);
	float B = length(v1) * length(v2);
	B = acos(abs(A) / (B + 0.00001));
	if (A < 0) B = 3.14159265 - B;
	return B;
}





//等距圆柱UV
Inline vec2 f_equirectangularUV(vec3 dir) {
	vec2 uv;
	dir = f_cartesianToSpherical(dir);

	uv.x = dir.x / (2 * M_PI);
	//uv.x = dir.x;
	uv.y = dir.y / M_PI;

	uv = clamp(uv, 0, 1);
	uv.y = 1 - uv.y;

	return uv;
}

//圆柱UV
Inline vec2 f_CylindricalProjectUV(vec3 dir) {
	vec2 uv;
	dir = f_cartesianToSpherical(dir);

	uv.x = dir.x / 2*M_PI;
	uv.y = dir.y;
	return uv;
}







//-------------------------------------- 随机 -------------------------------------------------
Inline float random(float v) {
	return fract(sin(v) * 43758.5453123);
}

Inline vec2 random(in vec2 v) {
	vec2 rv0;
	vec2 rv1;
	rv0.x = 90.12;
	rv0.y = 314.73;
	rv1.x = 237.3;
	rv1.y = 113.7;

	vec2 r;
	r.x = dot(v, rv0);
	r.y = dot(v, rv1);
	r.x = -1.0f + 2.0 * fract(sin(r.x) * 568451.12456731);
	r.y = -1.0f + 2.0 * fract(sin(r.y) * 873123.49382831);
	return r;
}



//Inline vec2 random(in vec2 uv) {
//	vec2 tempA;
//	tempA.x = 13.9157;
//	tempA.y = 79.233;
//	vec2 tempB;
//	tempB.x = random(13.9157);
//	tempB.y = random(79.233);
//
//	vec2 r;
//	r.x = fract(sin(dot(uv, tempA)) * 43758.5453123);
//	r.y = fract(sin(dot(uv, tempB)) * 43758.5453123);
//	return r;
//}

Inline vec3 random(in vec3 v) {
	vec3 rv0;
	vec3 rv1;
	vec3 rv2;
	rv0.x = 90.12;
	rv0.y = 314.73;
	rv0.z = 157.3;

	rv1.x = 237.3;
	rv1.y = 10.73;
	rv1.z = 113.7;

	rv2.x = 331.97;
	rv2.y = 33.5;
	rv2.z = 73.9;

	vec3 r;
	r.x = dot(v, rv0);
	r.y = dot(v, rv1);
	r.z = dot(v, rv2);
	r.x = -1.0f + 2.0 * fract(sin(r.x) * 568451.12456731);
	r.y = -1.0f + 2.0 * fract(sin(r.y) * 853211.14567823);
	r.z = -1.0f + 2.0 * fract(sin(r.y) * 135794.15732973);
	return r;
}








Inline vec3 f_SphereSampling(vec2 uv) {
	vec3 coord;
	coord.x = sin(uv.y) * cos(uv.x);
	//coord.y = sin(uv.y);
	coord.y = cos(uv.y);
	coord.z = sin(uv.y) * sin(uv.x);
	return coord;
}
Inline vec3 f_SphereSampling2(vec2 uv) {
	vec3 coord;
	coord.x = sin(uv.y) * cos(uv.x);
	coord.y = sin(uv.y) * sin(uv.x);
	coord.z = cos(uv.y);
	return coord;
}


Inline vec3 f_SphereSampling_toWorld(vec3 ss, vec3 N) {
	vec3 up;
	up.x = 0.0001;
	up.y = 1;
	up.z = 0.0001;

	vec3 right = normalize(cross(up, N));
	up = normalize(cross(N, right));

	return right * ss.x + N * ss.y + up * ss.z;
}
Inline vec3 f_SphereSampling_toWorld2(vec3 ss, vec3 N) {
	vec3 up;
	up.x = 0.00001;
	up.y = 1;
	up.z = 0.00001;

	vec3 right = normalize(cross(up, N));
	up = normalize(cross(N, right));

	return right * ss.x + N * ss.z + up * ss.y;
}




//���ι�Ӱ
Inline float f_GeometrySchickGGX(float N_dot_V, float roughness) {
	//float denom = N_dot_V * (1.0 - roughness) + roughness;
	//return N_dot_V / denom;
	
	float r = (roughness + 1.0);
	float k = (r * r) / 8.0;
	float num = N_dot_V;
	float denom = N_dot_V * (1.0 - k) + k;
	return num / denom;
}

Inline float f_GeometrySmith(in vec3 N, in vec3 V, in vec3 L, float roughness) {
	float N_dot_V = max(dot(N, V), 0);
	float N_dot_L = max(dot(N, L), 0);
	//float N_dot_V = abs(dot(N, V));
	//float N_dot_L = abs(dot(N, L));
	float ggx1 = f_GeometrySchickGGX(N_dot_V, roughness);
	float ggx2 = f_GeometrySchickGGX(N_dot_L, roughness);

	return ggx1 * ggx2;
}

//����߹�ֲ�
Inline float f_DistributionGGX(in vec3 N, vec3 V_L, float roughness) {
	float roughness2 = roughness * roughness;
	roughness2 = roughness2 * roughness2;

	float NdotH = max(dot(N, V_L), 0);
	//float NdotH = abs(dot(N, V_L));
	float NdotH2 = NdotH * NdotH;

	float denom = NdotH2 * (roughness2 - 1.0) + 1.0;
	denom = M_PI * denom * denom;
	return roughness2 / denom;
}

//�����
Inline vec3 f_fresnelSchlick(float cosThete, vec3 F0) {
	return F0 + (1.0 - F0) * pow(clamp(1.0 - cosThete, 0.0, 1.0), 0.5);
}


Inline vec2 f_uv_spherical(in vec3 point, in vec3 size) {
	//vec2 uv;

	vec3 v1;
	v1.x = point.x - size.x;
	v1.y = 0;
	v1.z = point.z - size.z;
	v1 = normalize(v1);

	vec3 v2;
	v2.x = 1;
	v2.y = 0;
	v2.z = 0;


	vec2 sampling;
	float angle = (dot(v1, v2));

	sampling.x = acos(angle) * (M_PI*2);
	sampling.y = sin(point.y * (M_PI*2));
	
	return sampling;
}

Inline float f_squaredNorm(vec3 v) {
	return v.x * v.x + v.y * v.y + v.z * v.z;
}


Inline float f_graph_vec_to_radians_180(in vec3 vec0, in vec3 vec1) {
	float angleA = (dot(vec0, vec1));
	float angleB = length(vec0) * length(vec1);
	angleB = acos(min(float(abs(angleA) / (angleB + 0.0000001)), 1.0f));
	if (angleA < 0) {
		angleB = 3.14159265 - angleB;
	}
	//if (dot(cross(vec0, vec1), cross(vec0, vec0 - vec1)) < 0) {
	//	angleB += 3.14159265;
	//}
	return angleB;
}



DEF_graph_vec_build_quat {
	float h = angle * 0.5f;
	float w = cos(h);

	vec3 v = dir * sin(h);
	vec4 quat;
	quat.x = v.x;
	quat.y = v.y;
	quat.z = v.z;
	quat.w = w;

	return quat;
}


DEF_graph_quatTranformInv {
	vec3 qv;
	qv.x = q.x;
	qv.y = q.y;
	qv.z = q.z;

	vec3 newPos = pos * (2.0f * q.w * q.w - 1.0f);
	newPos = newPos - (cross(qv, pos) * q.w * 2.0f) + (qv * dot(qv, pos) * 2.0f);
	return newPos;
}

DEF_surface_FaceNormal {
	vec3 e0 = (v1 - v0);
	vec3 e1 = (v2 - v0);
	return (cross(e0, e1));
}


DEF_glsl_CoordToIndex {
	uint l = dim.x * dim.y;
	uint index = (l * coord.z) + (coord.y * dim.x) + coord.x;
	return index;
}

DEF_glsl_IndexToCoord {
	uint L = dim.x * dim.y;
	ivec3 coord;
	coord.z = int(index / L);
	uint s = index - uint(coord.z) * L;
	coord.y = int(s / dim.x);
	coord.x = int(s - (coord.y * dim.x));
	return coord;
}



DEF_glsl_bspline {
	float w = 0.0;
	float x = length(dis);

	if (x < 1.0*r) {
		w = (1.0 / 6.0) * (pow(max(2.0 - x/r, 0), 3.0f) - 4 * pow(max(1 - x/r, 0), 3.0f));
	}
	else if (x >= 1.0*r && x < 2.0*r) {
		w = (1.0 / 6.0) * pow(max(2.0 - x/r, 0.0f), 3);
	}
	return w;
}

DEF_glsl_quadratic {
	float w = 0.0;
	float x = length(dis);

	if (x <= 0.5*r) {
		w = -3.0 * x * x + 0.75;
	}
	else if (x > 0.5*r && x <= 1.5*r) {
		w = 0.5 * pow(max(x - 1.5*r, 0), 2);
	}
	return w;
}

//W_poly6
DEF_glsl_polynomial {
	d /= r;
	
	if (d >= 0 && d <= 1) {
		float h_sqr = (1 - d * d);
		return 315.0f / (64.0f * 3.141592 * pow(r, 9)) * pow(h_sqr, 3);
		//return 315.0f / (64.0f * 3.141592 * pow(r, 9)) * pow((h_sqr - d_sqr), 3);
	}
	else {
		return 0.0f;
	}
}

Inline float f_SpikyGradient(float r, float h) {
	if (r >= h) {
		return 0.0f;
	}
	else {
		return -6 * (h - r) * (h - r) / (h * h * h * M_PI);
	}
}

Inline float f_W_Poly6(float r, float h) {
	float h_square = h * h;
	float coefficient = 315.0 / (201.0619298297 * pow(h, 9));
	//float coefficient = 315.0 / (64.0 * M_PI * pow(h, 9));
	return coefficient * pow(h_square - r * r, 3);
}
Inline float f_W_Poly6_2(float r, float h) {
	float h_square = h * h;
	if (r > h_square)
		return 0.0f;
	float diff = h_square - r;
	return 315.0f / (64.0f * M_PI * pow(h, 9)) * diff * diff * diff;
}



Inline float f_W_spiky_poly6_derivative(float r, float h) {
	//if (r < h) {
	//	return 45.0 * (h-r) / (M_PI * pow(h, 6));
	//}
	//else {
	//	return 0;
	//}

	//计算r/h的值
	float rh = r / h;

	//当r/h的值在0和1之间时，计算W_spiky_poly6_derivative函数的值
	if (0 < rh && rh <= 1) {
		float u3 = (1.0 - rh) * (1.0 - rh) * (1.0 - rh);
		return -45.0 / (M_PI * pow(h, 6)) * u3 * rh;
		//return -45.0 / (M_PI * pow(h, 6)) * (h - r);
	}
	//否则返回0
	else {
		return 0;
	}
}




Inline float Poly6(float r, float radius) {
	//if (r > 1.0e-6) {
	float m_k = (8.0) / (M_PI * pow(radius, 3));

	float q = r / radius;
	if (q <= 0.5) {

		float q2 = q * q;
		float q3 = q2 * q;

		return m_k * (6 * q3 - 6 * q2 + 1);
	}
	else {
		return m_k * (pow(1 - q, 3) * 2);
	}
	//}
	return 0;
}

Inline float wPoly6(vec3 r, float radius) {
	float lengthSquared = f_squaredNorm(r);
	if(lengthSquared > radius || lengthSquared < 1e-7) return 0;

	float iterm = radius - lengthSquared;
	return 315 / (64 * M_PI * pow(radius, 9)) * pow(iterm, 3);
}

Inline vec3 poly6KernelGrad(in vec3 r, float len, float radius) {
	vec3 ren;
	//ren.x = 0;
	//ren.y = 0;
	//ren.z = 0;
	//
	//float lengthSquared = f_squaredNorm(r);
	//if (lengthSquared > radius || lengthSquared < 1e-7) return ren;
	//
	//float iterm = radius - len;
	//float sk = (45 / (M_PI * pow(radius, 6))) * pow(iterm, 2) / len;
	//return r * sk;

	//if (len > 1.0e-6) {
	float m_l = 48.0 / (M_PI * pow(radius, 3));

	float q = len / radius;
	vec3 grad = r * (1 / (len * radius));
	if (q <= 0.5) {
		ren = grad * m_l * q * (3.0 * q - 2.0);
	}
	else {
		float factor = 1 - q;
		ren = grad * m_l * (-factor * factor);
	}
	//}
	
	return ren;
}



Inline vec2 f_fibonacci_spiral(int n, float r) {
	int a = 0, b = 1;
	while (n > 1) {
		int t = a;
		a = b;
		b += t;
		--n;
	}

	vec2 coord;
	r *= b;
	float theta = r * M_PI / 180.0f * (3.0f - sqrt(5.0f));
	coord.x = r * cos(theta);
	coord.y = r * sin(theta);

	return coord;
}


Inline vec2 generate_point(int index, int num_points, float circle_area, float f) {
	// 黄金角度（Golden Angle）是黄金分割法的一个应用，它是360度与黄金比例的乘积
	float golden_angle = 2.0 * M_PI * (3.0 - sqrt(f));  // 黄金角度

	// 计算每个点所占的面积
	float point_area = circle_area / num_points;

	// 根据点的面积计算点的半径
	float point_radius = sqrt(point_area / M_PI);

	// 使用黄金角度来计算点的角度
	float angle = index * golden_angle;

	// 使用点的半径和角度来计算点的坐标
	float r = point_radius + index * 2.0 * point_radius;  // 半径
	vec2 point;
	point.x = r * cos(angle);
	point.y = r * sin(angle);

	return point;
}


DEF_glsl_calculateTangentPoints {
	float dis = length(center[0] - center[1]);
	float angle = atan2(center[1].y - center[0].y, center[1].x - center[0].x);

	float lineAngle = acos(r[0] - r[1]) / dis;

	tp[0].x = center[0].x + r[0] * cos(angle + lineAngle);
	tp[0].y = center[0].y + r[0] * sin(angle + lineAngle);

	tp[1].x = center[1].x + r[1] * cos(angle + lineAngle);
	tp[1].y = center[1].y + r[1] * sin(angle + lineAngle);
}


Inline vec3 f_glsl_HSVToRGB(float h, float s, float v) {
	vec3 rgb;

	int i;
	float f, p, q, t;
	if (s == 0) {
		rgb.x = rgb.y = rgb.z = v;
	}
	else {
		h *= 6.0f;			// sector 0 to 5
		i = int(floor(h));
		f = h - i;			// factorial part of h
		p = v * (1 - s);
		q = v * (1 - s * f);
		t = v * (1 - s * (1 - f));
		switch (i) {
			case 0:
				rgb.x = v;
				rgb.y = t;
				rgb.z = p;
				break;
			case 1:
				rgb.x = q;
				rgb.y = v;
				rgb.z = p;
				break;
			case 2:
				rgb.x = p;
				rgb.y = v;
				rgb.z = t;
				break;
			case 3:
				rgb.x = p;
				rgb.y = q;
				rgb.z = v;
				break;
			case 4:
				rgb.x = t;
				rgb.y = p;
				rgb.z = v;
				break;
			default:		// case 5:
				rgb.x = v;
				rgb.y = p;
				rgb.z = q;
				break;
		};
	}

	return rgb;
}


Inline float f_glsl_pointToCylinderDistance(const vec3 point, const vec3 cylinderCenter, const float radius, const float height) {
	// 计算点到圆柱体中心的距离
	vec3 d = point - cylinderCenter;
	float distanceToCenter = length(d);

	// 计算点在圆柱体轴线上的投影点
	float projectedPointX = d.x;
	float projectedPointY = d.y;
	float projectedPointZ = d.z - (d.x / (d.x * d.x + d.y * d.y) * (height * 0.5));

	// 判断点是否在圆柱体内
	if (distanceToCenter <= radius + height * 0.5) {
		// 点在圆柱体内，计算点到最近的生成线（线段）的距离
		vec3 closestPointOnLine;
		closestPointOnLine.x = projectedPointX;
		closestPointOnLine.y = projectedPointY;
		closestPointOnLine.z = projectedPointZ + radius * (point.z - projectedPointZ) / (height * 0.5);
		float distanceToLine = length((point - closestPointOnLine));
		return -distanceToLine;
	}
	else {
		// 点在圆柱体外，计算点到圆柱体表面的最小距离
		vec3 closestPointOnSurface;
		closestPointOnSurface.x = point.x;
		closestPointOnSurface.y = point.y;
		closestPointOnSurface.z = point.z - (d.x / (d.x * d.x + d.y * d.y) * (height * 0.5));
		float distanceToSurface = length(closestPointOnSurface - cylinderCenter);
		return distanceToSurface - radius;
	}
}









/******************************** 模糊算法 **********************************/


Inline float f_glsl_gaussianWeight(float x, float sigma) {
	return exp(-(x * x) / (2.0 * sigma * sigma)) / (2.0 * 3.14159265 * sigma * sigma);
}
Inline float f_glsl_gaussianWeight(float x, float y, float sigma) {
	return exp(-(x * x + y * y) / (2.0 * sigma * sigma)) /
		(2.0 * 3.14159265 * sigma * sigma);
}






#undef in
#undef out

// A B C  ABt = (AC*AB)*AB  | ACt = (AB*AC)*AC


#endif //INCLUDE_SHADER_BUILT_IN_FUNCTIONS


/*


DEF_glsl_bspline {
	float w = 0.0;
	float x = length(dis);

	if (x < 1.0) {
		w = (1.0 / 6.0) * (pow((2.0 - x), 3) - 4 * pow((1.0 - x), 3));
	}
	else if (x >= 1.0 && x < 2.0) {
		w = (1.0 / 6.0) * pow((2.0 - x), 3);
	}
	return w;
}

DEF_glsl_quadratic {
	float w = 0.0;
	float x = length(dis);

	if (x <= 0.5) {
		w = -3.0 * x * x + 0.75;
	}
	else if (x > 0.5 && x <= 1.5) {
		w = 0.5 * pow((x - 1.5), 2);
	}
	return w;
}



DEF_glsl_bspline {
	float w = 0.0;
	float x = length(dis);
	float l = x / r;

	if (x < r) {
		w = (1.0 / 6.0) * (pow((2.0 - l), 3) - 4 * pow((1.0 - l), 3));
	}
	else if (x >= r && x < 2.0 * r) {
		w = (1.0 / 6.0) * pow((2.0 - l), 3);
	}
	return w;
}

DEF_glsl_quadratic {
	float w = 0.0;
	float x = length(dis);

	if (x <= r) {
		w = -3.0 * x * x + 0.75;
	}
	else if (x > r && x <= 2*r) {
		w = 0.5 * pow((x - 2*r), 2);
	}
	return w;
}



DEF_glsl_bspline {
	float w = 0.0;
	float x = length(dis);

	if (x < 1.0*r) {
		w = (1.0 / 6.0) * (pow(max(2.0*r - x, 0), 3) - 4 * pow(max(r - x, 0), 3));
	}
	else if (x >= 1.0*r && x < 2.0*r) {
		w = (1.0 / 6.0) * pow(max(2.0*r - x, 0), 3);
	}
	return w;
}

DEF_glsl_quadratic {
	float w = 0.0;
	float x = length(dis);

	if (x <= 0.5*r) {
		w = -3.0 * x * x + 0.75;
	}
	else if (x > 0.5*r && x <= 1.5*r) {
		w = 0.5 * pow(max(x - 1.5*r, 0), 2);
	}
	return w;
}




*/